package com.etlmaster.executor.utils;

import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import freemarker.core.Environment;
import freemarker.core.ExtBuildIn;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;

public class StringUtils {


	static final int INDEX_NOT_FOUND = -1;

	// 小数
	static Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]+");

	static Pattern IntegerPattern = Pattern.compile("-?[0-9]*$");

	public static final String EMPTY = "";

	// 如果是整数时会返回false,增加整数模式判断
	public static boolean isNumberic(String text) {
		if (text.equals("") || text == null) {
			return false;
		}
		if (text.indexOf(".") > 0) {
			return pattern.matcher(text.replace(" ", "")).matches();
		} else {
			return IntegerPattern.matcher(text.replace(" ", "")).matches();
		}
	}

	public static Object parseNumber(String text) {
		if (isNumberic(text)) {
			if (text.indexOf(".") > 0) {
				return Double.valueOf(text);
			} else {
				return Integer.valueOf(text);
			}
		} else {
			return text;
		}
	}

	public static String[] parseFixedWidth(String row, int[] lengths) {
		String[] result = new String[lengths.length];
		int begin = 0;
		for (int i = 0; i < lengths.length; i++) {
			char[] dst = new char[lengths[i]];
			row.getChars(begin, begin + lengths[i], dst, 0);
			result[i] = String.valueOf(dst).trim();
			begin += lengths[i];
		}
		return result;
	}

	public static String replaceSql(String str) {
		String dest = "";
		if (str != null) {
			Pattern p = Pattern.compile("\r|\n");
			Matcher m = p.matcher(str);
			dest = m.replaceAll("");
		}
		return dest;
	}

	public static String join(List<String> array, String separator) {
		return join(array.toArray(), separator);
	}

	public static String join(Object[] array, String separator) {
		if (array == null) {
			return null;
		}
		if (separator == null) {
			separator = EMPTY;
		}
		int arraySize = array.length;

		int bufSize = ((arraySize == 0) ? 0
				: arraySize * ((array[0] == null ? 16 : array[0].toString().length()) + separator.length()));

		StringBuffer buf = new StringBuffer(bufSize);

		for (int i = 0; i < arraySize; i++) {
			if (i > 0) {
				buf.append(separator);
			}
			if (array[i] != null) {
				buf.append(array[i]);
			}
		}
		return buf.toString();
	}

	public static String substringBetween(String str, String open, String close) {
		if (str == null || open == null || close == null) {
			return null;
		}
		int start = str.indexOf(open);
		if (start != INDEX_NOT_FOUND) {
			int end = str.indexOf(close, start + open.length());
			if (end != INDEX_NOT_FOUND) {
				return str.substring(start + open.length(), end);
			}
		}
		return null;
	}

	/**
	 * 使用Freemarker引擎替换变量
	 * 
	 * @param text
	 * @param data
	 * @return
	 */
	public static String variableSubstitution(String text, Object data) {
		new ExtBuildIn(new CalDateBI());//TODO 后面需要改造通过Annotation来实现
		StringWriter sw = new StringWriter();
		try {
			Template template = new Template(null, text, null);
			template.process(data, sw);
			LogWriter.addLog("DEBUG","原始文本:{}，替换后:{}", text, sw.toString());
		} catch (Exception e) {
			LogWriter.addLog("WARN","替换变量失败,{},请检查({})是否声明", text, getErrorVar(text, (Map<String, Object>) data));

			return null;
		}
		return sw.toString();
	}

	// fengwen 20150402 获取未声明的变量列表，提醒开发人员
	protected static String getErrorVar(String text, Map<String, Object> obj) {
		try {

			String regex = "(\\$\\{{1})([\\w]*)(\\}{1})";// 只能匹配字符串

			regex = "(\\$\\{{1})(.*?[a-zA-Z\\\\d]+.*?)(\\}{1})";// 能匹配任意字符
			List<String> ls = new ArrayList<String>();
			Map<String, String> map = new HashMap<String, String>();
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(text);

			while (m.find()) {
				String tmp = m.group();
				String varName = m.group(2);
				map.put(varName, tmp);
			}

			for (Map.Entry<String, String> entry : map.entrySet()) {
				String key = entry.getKey();
				String value = entry.getValue();
				if (obj == null) {
					ls.remove(value);
					ls.add(value);
				} else {
					if (obj.get(key) == null) {
						ls.remove(value);
						ls.add(value);
					}
				}

			}

			return ls.toString();
		} catch (Exception ex) {

			return "";
		}
	}

	/**
	 * 计算日期的函数
	 * 
	 * @author MeiKefu
	 */
	static class CalDateBI extends ExtBuildIn.ExtBuildInModel {
		public String getName() {
			return "calDate";
		}

		public TemplateModel calculateResult(final String s, final Environment env) throws TemplateException {
			return new TemplateMethodModelEx() {
				public Object exec(List args) throws TemplateModelException {
					int amount = -1;
					if (args.size() > 0 && args.get(0) != null) {
						String arg1 = args.get(0).toString();
						if (StringUtils.isNumberic(arg1)) {
							amount = Integer.valueOf(arg1);
						}
					}
					String cycle = "day";
					if (args.size() > 1 && args.get(1) != null) {
						cycle = args.get(1).toString();
					}
					String format = "yyyyMMddHHmmss";
					format = format.substring(0, s.length());

					// fengwen 20150402支持参数格式化自定义传入
					if (args.size() > 2 && args.get(2) != null) {
						format = args.get(2).toString();
					}

					int year = 2015;
					int month = 1;
					int day = 1;
					int hour = 0;
					int minute = 0;
					int second = 0;
					if (s.length() > 3) {
						year = Integer.valueOf(s.substring(0, 4));
					}

					if (s.length() > 5) {
						month = Integer.valueOf(s.substring(4, 6)) - 1;
					}

					if (s.length() > 7) {
						day = Integer.valueOf(s.substring(6, 8));
					}

					if (s.length() > 9) {
						hour = Integer.valueOf(s.substring(8, 10));
					}

					if (s.length() > 11) {
						minute = Integer.valueOf(s.substring(10, 12));
					}

					if (s.length() > 13) {
						second = Integer.valueOf(s.substring(12, 14));
					}
					GregorianCalendar calendar = new GregorianCalendar(year, month, day, hour, minute, second);

					int field = Calendar.DATE;

					if ("month".equalsIgnoreCase(cycle) || "m".equalsIgnoreCase(cycle)) {
						field = Calendar.MONTH;
					} else if ("year".equalsIgnoreCase(cycle) || "y".equalsIgnoreCase(cycle)) {
						field = Calendar.YEAR;
					} else if ("hour".equalsIgnoreCase(cycle) || "h".equalsIgnoreCase(cycle)) {
						field = Calendar.HOUR_OF_DAY;
						// format = "yyyyMMddHH";
					} else if ("minute".equalsIgnoreCase(cycle) || "mi".equalsIgnoreCase(cycle)) {
						field = Calendar.MINUTE;
					} else if ("second".equalsIgnoreCase(cycle) || "s".equalsIgnoreCase(cycle)) {
						field = Calendar.SECOND;
					} else if ("last".equalsIgnoreCase(cycle) || "l".equalsIgnoreCase(cycle)) {// 判断取每月最后一天
						field = Calendar.MONTH;
						amount = amount + 1;
					}
					calendar.add(field, amount);
					if ("last".equalsIgnoreCase(cycle) || "l".equalsIgnoreCase(cycle)) {
						calendar.set(Calendar.DAY_OF_MONTH, 0);
					}
					return new SimpleDateFormat(format).format(calendar.getTime());
				}
			};
		}
	}

	public static void main(String[] args) {
		System.out.println(StringUtils.isNumberic(" 1.2"));

		System.out.println(StringUtils.isNumberic(" - 1.2"));
	}
}
